import { applyDecorators, createParamDecorator, ExecutionContext, HttpStatus, SetMetadata, Type } from "@nestjs/common";
import { ApiExtraModels, ApiResponse, getSchemaPath } from "@nestjs/swagger";
import { MyResponse, PaginationData } from "src/common/model";
import { EXCLUDE_TRANSFORM_KEY, PUBLIC_KEY } from "src/constant";

// 获取请求用户信息
export const RequsetUser = createParamDecorator((key: keyof RequsetUser, ctx: ExecutionContext) => {
    const user = ctx.switchToHttp().getRequest()?.user || ctx.switchToWs().getClient()?.user;
    return user && key ? user[key] : user;
});

// 公开接口
export function Public() {
    return SetMetadata(PUBLIC_KEY, true);
}

export function ExcludeTransform() {
    return SetMetadata(EXCLUDE_TRANSFORM_KEY, true);
}

function genBaseProp(type: Type<any>) {
    if (["String", "Number", "Boolean"].includes(type.name)) {
        return { type: type.name.toLocaleLowerCase() };
    } else {
        return { $ref: getSchemaPath(type) };
    }
}

// Api 响应类型
export function ApiRes<T extends Type>({
    type,
    code = HttpStatus.OK,
    pagination = false,
}: {
    type?: T | T[];
    code?: HttpStatus;
    pagination?: boolean;
}) {
    let prop: any = { type: "null", default: null };

    if (type instanceof Array) {
        prop = { type: "array", items: genBaseProp(type[0]) };
    } else if (type && pagination) {
        prop = {
            $ref: getSchemaPath(PaginationData),
            properties: {
                list: {
                    type: "array",
                    items: genBaseProp(type),
                },
            },
        };
    } else if (type) {
        prop = genBaseProp(type);
    }

    return applyDecorators(
        ApiExtraModels(Array.isArray(type) ? type[0] : type),
        ApiResponse({
            status: code,
            schema: {
                $ref: getSchemaPath(MyResponse),
                properties: {
                    data: prop,
                },
            },
        }),
    );
}

export * from "./permission";
